package com.lbjhan.rpc.serializer;

import com.lbjhan.rpc.pojo.User;
import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

public class ProtostuffSerializer<T> implements ISerializer{

    private static LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);

    private static Map<Class<?>, Schema<?>> schemaCache = new ConcurrentHashMap<>();

    @Override
    public byte[] serialize(Object obj){
        Schema<T> schema = (Schema<T>) getSchema(obj.getClass());
        byte[] bytes = ProtostuffIOUtil.toByteArray((T)obj, schema, buffer);
        return bytes;
    }

    @Override
    public T deserialize(byte[] bytes, Class clazz){
        Schema<T> schema = getSchema(clazz);
        T t = schema.newMessage();
        ProtostuffIOUtil.mergeFrom(bytes, t, schema);
        return t;
    }

    private <T> Schema<T> getSchema(Class<T> clazz){
        Schema<T> schema =(Schema<T>) schemaCache.get(clazz);
        if(Objects.isNull(schema)){
            schema = RuntimeSchema.getSchema(clazz);
            if(Objects.nonNull(schema)){
                schemaCache.put(clazz, schema);
            }
        }
        return schema;
    }

    public static void main(String[] args) {
        ProtostuffSerializer<User> userProtostuffSerializer = new ProtostuffSerializer<>();
        byte[] bytes = userProtostuffSerializer.serialize(new User(1, "tom"));
        System.out.println(bytes.length);
        User user = userProtostuffSerializer.deserialize(bytes, User.class);
        System.out.println(user);
        /**
         * 7
         * User(id=1, name=tom)
         */
    }
}
